package com.iceGame;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.World;

public class PhysicsWorld {

	static final short CATEGORY_ICE = 0x0001;   
	static final short CATEGORY_FIREBALL = 0x0002; 
	static final short CATEGORY_PLATFORM = 0x0004; 
	static final short CATEGORY_SCENERY = 0x0008;
	
	static final short MASK_ICE = CATEGORY_PLATFORM | CATEGORY_SCENERY ; 
	static final short MASK_FIREBALL = CATEGORY_SCENERY; 
	static final short MASK_PLATFORM = CATEGORY_ICE | CATEGORY_SCENERY;
	static final short MASK_SCENERY = -1;
	
	public static final int WORLD_STATE_RUNNING = 0;
	public static final int WORLD_STATE_NEXT_LEVEL = 1;
	public static final int WORLD_STATE_GAME_OVER = 2;
	public Rectangle bounds = new Rectangle(640,400,160,80);
	public World world;
	public double score;
	public int numOfStars = 0;
	public Level currentLevel;
	public int topLevel = 9;
	public int state;

	public PhysicsWorld() {
		createWorld();
		score = 0;
	}

	public PhysicsWorld(String level) {
		createWorld(level);
		score = 0;
	}

	public void createWorld(String level) {
		numOfStars = 0;
		Vector2 gravity = new Vector2(0f, -10f);
		boolean doSleep = false;
		world = new World(gravity, doSleep);
		FileHandle fh = Gdx.files.internal("data/world/level1/" + level
				+ ".xml");
		currentLevel = Level.loadLevel(fh, this);
		state = WORLD_STATE_RUNNING;
	}

	public void createWorld() {
		createWorld("level1");
	}

	public void update(float deltaTime) {
		switch (state) {
		case WORLD_STATE_NEXT_LEVEL:
			updateNextLevel(deltaTime);
			break;
		case WORLD_STATE_GAME_OVER:
			updateGameOver(deltaTime);
			break;
		case WORLD_STATE_RUNNING:
			updateGameRunning(deltaTime);
			break;
		}

	}

	private void updateGameRunning(float deltaTime) {
		checkLevelEnd();
		updateFireballs(deltaTime);
		updateFires(deltaTime);
		updateMovingPlatforms(deltaTime);
		checkCollectableIceCollisions();
			//check fireball collision
		checkFireballCollision();
		checkFireCollisions();
		checkUserControls(deltaTime);
		world.step(deltaTime, 5, 5);
	}

	private void checkUserControls(float deltaTime) {
		float yValue = Gdx.input.getAccelerometerY();
		float angle = yValue * 9 + 90;
		world.setGravity(new Vector2(currentLevel.gravity * MathUtils.cosDeg(angle), currentLevel.gravity
				* MathUtils.sinDeg(angle)));

		float accelY = -10f;
		
		if ((Gdx.input.isTouched() || Gdx.input.isKeyPressed(Keys.SPACE))
		/*&& iceCube.state != IceCube.JUMPING*/ & currentLevel.iceCube.canJump(world) ) {
			GameScreen.guiCam.unproject(GameScreen.touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
			if (!OverlapTester.pointInRectangle(bounds, GameScreen.touchPoint.x,GameScreen.touchPoint.y)){
				currentLevel.iceCube.jump();
				if (Settings.soundEnabled)
					Assets.jumpSound.play();
			}

		}
		currentLevel.iceCube.update(deltaTime);

		if (Gdx.app.getType() == Application.ApplicationType.Desktop) {
			float accel = 0;
			if (Gdx.input.isKeyPressed(Keys.DPAD_LEFT))
				accel = -20f;
			if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT))
				accel = 20f;
			world.setGravity(new Vector2(accel, accelY));
		}
	}

	private void checkFireCollisions() {
		for (int i = 0; i < currentLevel.fires.size();i++){
			Fire fire = currentLevel.fires.get(i);
			if (OverlapTester.overlapRectangles(currentLevel.iceCube.bounds,fire.bounds)){
				state = WORLD_STATE_GAME_OVER;
			}
		}
	}

	private void checkCollectableIceCollisions() {
		for (int i = 0; i < currentLevel.collectables.size(); i++) {
			CollectableGameObject temp = currentLevel.collectables.get(i);
			//CollectableIce temp = (CollectableIce) currentLevel.collectables.get(i); //TODO remove casting
			if (OverlapTester.overlapRectangles(currentLevel.iceCube.bounds, temp.bounds)) {
				if (Settings.soundEnabled)
					Assets.collectSound.play(); 
				currentLevel.collectables.remove(temp);
				if (currentLevel.iceCube.bounds.width<=5)
						currentLevel.iceCube.CubeEnlarge();
			}
		}
	}

	private void checkLevelEnd() {
		if (OverlapTester.overlapRectangles(currentLevel.iceCube.bounds, currentLevel.destination.entrance)) {
			state = WORLD_STATE_NEXT_LEVEL;
			score += currentLevel.iceCube.bounds.height*currentLevel.iceCube.bounds.width * 100;
		}
	}

	private void checkFireballCollision() {
		for (int i = 0; i < currentLevel.fireballs.size();i++){
			Fireball fireball = currentLevel.fireballs.get(i);
			if (OverlapTester.overlapRectangles(currentLevel.iceCube.bounds,fireball.getBounds()) && fireball.state == Fireball.NORMAL){
				//fireball.body.destroyFixture(fireball.body.getFixtureList().get(0));
				fireball.explode();
				//currentLevel.fireballs.remove(i);
				if (Settings.soundEnabled)
					Assets.explosionSound.play();
				
				
				if (currentLevel.iceCube.bounds.width>0.40){
					currentLevel.iceCube.CubeReduction(true);
				}
				else
					state=WORLD_STATE_GAME_OVER;
			}
			if (fireball.state == Fireball.DESTROIED){
				currentLevel.fireballs.remove(i);
			}
		}
	}
	private void updateMovingPlatforms(float deltaTime) {
		for (MovingPlatform m : currentLevel.movingPlatforms){
			m.update(deltaTime);
		}
		
	}

	private void updateFires(float deltaTime) {
		for (Fire f: currentLevel.fires){
			f.update(deltaTime);
		}
		
	}

	private void updateFireballs(float deltaTime) {
		for (Fireball f : currentLevel.fireballs) {
			f.update(deltaTime);
		}

	}

	private void updateGameOver(float deltaTime) {
		// TODO Auto-generated method stub

	}

	private void updateNextLevel(float deltaTime) {
		// TODO Auto-generated method stub
	}

}